package cn.com.anysdk.redis.demo.controller;

import cn.com.anysdk.redis.api.IRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Redis操作测试控制器
 * 展示AnySDK Redis的基础操作功能
 */
@RestController
@RequestMapping("/api/redis")
public class RedisOperationController {

    @Autowired
    private IRedisService redisService;

    /**
     * 测试连接
     */
    @GetMapping("/ping")
    public Map<String, Object> ping() {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean pong = redisService.ping();
            result.put("success", true);
            result.put("connected", pong);
            result.put("message", pong ? "Redis连接正常" : "Redis连接异常");
        } catch (Exception e) {
            result.put("success", false);
            result.put("connected", false);
            result.put("message", "连接失败: " + e.getMessage());
        }
        return result;
    }

    // ===== String操作 =====

    /**
     * 设置字符串值
     */
    @PostMapping("/string/set")
    public Map<String, Object> setString(@RequestBody Map<String, String> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = request.get("key");
            String value = request.get("value");
            String expireStr = request.get("expire");

            boolean success;
            if (expireStr != null && !expireStr.isEmpty()) {
                long expire = Long.parseLong(expireStr);
                success = redisService.setEx(key, value, expire);
                result.put("operation", "SETEX");
                result.put("expire", expire);
            } else {
                success = redisService.set(key, value);
                result.put("operation", "SET");
            }

            result.put("success", success);
            result.put("key", key);
            result.put("value", value);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 从列表左侧移除元素
     * @param key 列表键名
     * @return 移除的元素
     */
    @PostMapping("/list/lpop")
    public ResponseEntity<Map<String, Object>> lPop(@RequestBody Map<String, String> request) {
        try {
            String key = request.get("key");
            if (key == null || key.trim().isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "Key不能为空"
                ));
            }
            
            String result = redisService.lPop(key);
            return ResponseEntity.ok(Map.of(
                "success", true,
                "data", result != null ? result : "",
                "message", result != null ? "列表元素移除成功" : "列表为空"
            ));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of(
                "success", false,
                "message", "左侧元素移除失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 从列表右侧移除元素
     * @param key 列表键名
     * @return 移除的元素
     */
    @PostMapping("/list/rpop")
    public ResponseEntity<Map<String, Object>> rPop(@RequestBody Map<String, String> request) {
        try {
            String key = request.get("key");
            if (key == null || key.trim().isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "Key不能为空"
                ));
            }
            
            String result = redisService.rPop(key);
            return ResponseEntity.ok(Map.of(
                "success", true,
                "data", result != null ? result : "",
                "message", result != null ? "列表元素移除成功" : "列表为空"
            ));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of(
                "success", false,
                "message", "右侧元素移除失败: " + e.getMessage()
            ));
        }
    }

    /**
     * 获取字符串值
     */
    @GetMapping("/string/{key}")
    public Map<String, Object> getString(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            String value = redisService.get(key);
            long ttl = redisService.ttl(key);
            boolean exists = redisService.exists(key);

            result.put("success", true);
            result.put("key", key);
            result.put("value", value);
            result.put("exists", exists);
            result.put("ttl", ttl);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 删除键
     */
    @DeleteMapping("/string/{key}")
    public Map<String, Object> deleteKey(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean deleted = redisService.del(key);
            result.put("success", true);
            result.put("key", key);
            result.put("deleted", deleted);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    // ===== 键操作 =====

    /**
     * 检查键是否存在
     */
    @GetMapping("/key/{key}/exists")
    public Map<String, Object> keyExists(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean exists = redisService.exists(key);
            result.put("success", true);
            result.put("key", key);
            result.put("exists", exists);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 获取键的TTL
     */
    @GetMapping("/key/{key}/ttl")
    public Map<String, Object> keyTTL(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            long ttl = redisService.ttl(key);
            result.put("success", true);
            result.put("key", key);
            result.put("ttl", ttl);

            // 添加TTL状态说明
            String status;
            if (ttl == -1) {
                status = "永不过期";
            } else if (ttl == -2) {
                status = "键不存在";
            } else {
                status = "剩余 " + ttl + " 秒";
            }
            result.put("status", status);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 设置键的过期时间
     */
    @PostMapping("/key/{key}/expire")
    public Map<String, Object> keyExpire(@PathVariable String key, @RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            Object secondsObj = request.get("seconds");
            long seconds;
            if (secondsObj instanceof Integer) {
                seconds = ((Integer) secondsObj).longValue();
            } else if (secondsObj instanceof Long) {
                seconds = (Long) secondsObj;
            } else {
                seconds = Long.parseLong(secondsObj.toString());
            }

            long expireResult = redisService.expire(key, seconds);
            boolean success = expireResult == 1;

            result.put("success", success);
            result.put("key", key);
            result.put("seconds", seconds);
            result.put("result", expireResult);

            if (success) {
                result.put("message", "过期时间设置成功");
            } else {
                result.put("message", "键不存在或设置失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    // ===== Hash操作 =====

    /**
     * 设置Hash字段
     */
    @PostMapping("/hash/set")
    public Map<String, Object> setHash(@RequestBody Map<String, String> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = request.get("key");
            String field = request.get("field");
            String value = request.get("value");

            boolean success = redisService.hSet(key, field, value);
            result.put("success", success);
            result.put("key", key);
            result.put("field", field);
            result.put("value", value);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 获取Hash单个字段值
     */
    @GetMapping("/hash/{key}/{field}")
    public Map<String, Object> getHashField(@PathVariable String key, @PathVariable String field) {
        Map<String, Object> result = new HashMap<>();
        try {
            String value = redisService.hGet(key, field);
            result.put("success", true);
            result.put("key", key);
            result.put("field", field);
            result.put("data", value);
            
            if (value == null) {
                result.put("message", "字段不存在或键不存在");
            } else {
                result.put("message", "成功获取字段值");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "获取哈希字段值失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 获取Hash所有字段
     */
    @GetMapping("/hash/{key}")
    public Map<String, Object> getHash(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, String> hash = redisService.hGetAll(key);
            long len = redisService.hLen(key);
            Set<String> keys = redisService.hKeys(key);

            result.put("success", true);
            result.put("key", key);
            result.put("data", hash);
            result.put("length", len);
            result.put("filedCount",len);
            result.put("fields", keys);

            if (hash.isEmpty()) {
                result.put("message", "该键不存在或哈希为空");
            } else {
                result.put("message", String.format("成功获取 %d 个字段", len));
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "获取哈希字段失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 删除Hash字段
     */
    @DeleteMapping("/hash/{key}/{field}")
    public Map<String, Object> deleteHashField(@PathVariable String key, @PathVariable String field) {
        Map<String, Object> result = new HashMap<>();
        try {
            long deleted = redisService.hDel(key, field);
            boolean success = deleted > 0;
            
            result.put("success", success);
            result.put("key", key);
            result.put("field", field);
            result.put("deleted", deleted);
            
            if (success) {
                result.put("message", "字段删除成功");
            } else {
                result.put("message", "字段不存在或删除失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "删除哈希字段失败: " + e.getMessage());
        }
        return result;
    }

    // ===== List操作 =====

    /**
     * 向列表左侧添加元素
     */
    @PostMapping("/list/lpush")
    public Map<String, Object> lPushList(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = (String) request.get("key");
            @SuppressWarnings("unchecked")
            List<String> values = (List<String>) request.get("values");

            long length = redisService.lPush(key, values.toArray(new String[0]));
            
            result.put("success", true);
            result.put("operation", "LPUSH");
            result.put("key", key);
            result.put("values", values);
            result.put("length", length);
            result.put("message", "成功向列表左侧添加 " + values.size() + " 个元素");
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "向列表左侧添加元素失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 向列表右侧添加元素
     */
    @PostMapping("/list/rpush")
    public Map<String, Object> rPushList(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = (String) request.get("key");
            @SuppressWarnings("unchecked")
            List<String> values = (List<String>) request.get("values");

            long length = redisService.rPush(key, values.toArray(new String[0]));
            
            result.put("success", true);
            result.put("operation", "RPUSH");
            result.put("key", key);
            result.put("values", values);
            result.put("length", length);
            result.put("message", "成功向列表右侧添加 " + values.size() + " 个元素");
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "向列表右侧添加元素失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 向列表添加元素（通用方法，保留兼容性）
     */
    @PostMapping("/list/push")
    public Map<String, Object> pushList(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = (String) request.get("key");
            @SuppressWarnings("unchecked")
            List<String> values = (List<String>) request.get("values");
            String direction = (String) request.get("direction"); // "left" or "right"

            long length;
            if ("left".equals(direction)) {
                length = redisService.lPush(key, values.toArray(new String[0]));
                result.put("operation", "LPUSH");
            } else {
                length = redisService.rPush(key, values.toArray(new String[0]));
                result.put("operation", "RPUSH");
            }

            result.put("success", true);
            result.put("key", key);
            result.put("values", values);
            result.put("length", length);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 获取列表内容
     */
    @GetMapping("/list/{key}")
    public Map<String, Object> getList(@PathVariable String key,
                                       @RequestParam(defaultValue = "0") long start,
                                       @RequestParam(defaultValue = "-1") long end) {
        Map<String, Object> result = new HashMap<>();
        try {
            List<String> list = redisService.lRange(key, start, end);
            long length = redisService.lLen(key);

            result.put("success", true);
            result.put("key", key);
            result.put("list", list);
            result.put("length", length);
            result.put("range", start + " to " + end);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    // ===== Set操作 =====

    /**
     * 向集合添加元素
     */
    @PostMapping("/set/add")
    public Map<String, Object> addSet(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = (String) request.get("key");
            @SuppressWarnings("unchecked")
            List<String> members = (List<String>) request.get("members");

            long added = redisService.sAdd(key, members.toArray(new String[0]));
            long size = redisService.sCard(key);

            result.put("success", true);
            result.put("key", key);
            result.put("members", members);
            result.put("added", added);
            result.put("size", size);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    /**
     * 从集合移除元素
     */
    @PostMapping("/set/remove")
    public Map<String, Object> removeFromSet(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String key = (String) request.get("key");
            @SuppressWarnings("unchecked")
            List<String> members = (List<String>) request.get("members");

            long removed = redisService.sRem(key, members.toArray(new String[0]));
            long size = redisService.sCard(key);

            result.put("success", true);
            result.put("key", key);
            result.put("members", members);
            result.put("removed", removed);
            result.put("size", size);
            result.put("message", "成功移除 " + removed + " 个元素");
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "移除集合元素失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 检查元素是否在集合中
     */
    @GetMapping("/set/{key}/member/{member}")
    public Map<String, Object> isSetMember(@PathVariable String key, @PathVariable String member) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean isMember = redisService.sIsMember(key, member);
            long size = redisService.sCard(key);

            result.put("success", true);
            result.put("key", key);
            result.put("member", member);
            result.put("isMember", isMember);
            result.put("size", size);
            result.put("message", isMember ? "元素存在于集合中" : "元素不存在于集合中");
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("message", "检查元素失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 获取集合内容
     */
    @GetMapping("/set/{key}")
    public Map<String, Object> getSet(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        try {
            Set<String> members = redisService.sMembers(key);
            long size = redisService.sCard(key);

            result.put("success", true);
            result.put("key", key);
            result.put("members", members);
            result.put("size", size);
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }

    // ===== Key管理 =====

    /**
     * 获取匹配的键
     */
    @GetMapping("/keys")
    public Map<String, Object> getKeys(@RequestParam(defaultValue = "*") String pattern) {
        Map<String, Object> result = new HashMap<>();
        try {
            Set<String> keyNames = redisService.keys(pattern);
            List<Map<String, Object>> keyInfoList = new ArrayList<>();

            for (String key : keyNames) {
                Map<String, Object> keyInfo = new HashMap<>();
                try {
                    // 获取键的基本信息
                    String type = redisService.type(key);
                    long ttl = redisService.ttl(key);
                    boolean exists = redisService.exists(key);

                    keyInfo.put("key", key);
                    keyInfo.put("type", type);
                    keyInfo.put("ttl", ttl);
                    keyInfo.put("exists", exists);

                    // 根据类型获取值和大小
                    Object value = null;
                    long size = 0;

                    switch (type.toLowerCase()) {
                        case "string":
                            value = redisService.get(key);
                            size = value != null ? value.toString().length() : 0;
                            break;
                        case "hash":
                            Map<String, String> hashValue = redisService.hGetAll(key);
                            value = hashValue;
                            size = redisService.hLen(key);
                            break;
                        case "list":
                            List<String> listValue = redisService.lRange(key, 0, 10); // 只获取前10个元素
                            value = listValue;
                            size = redisService.lLen(key);
                            break;
                        case "set":
                            Set<String> setValue = redisService.sMembers(key);
                            value = setValue;
                            size = redisService.sCard(key);
                            break;
                        case "zset":
                            Set<String> zsetValue = redisService.zRange(key, 0, 10); // 只获取前10个元素
                            value = zsetValue;
                            size = redisService.zCard(key);
                            break;
                        default:
                            value = "未知类型";
                            size = 0;
                    }

                    keyInfo.put("value", value);
                    keyInfo.put("size", size);

                    keyInfoList.add(keyInfo);
                } catch (Exception e) {
                    // 如果获取某个键的信息失败，记录错误但继续处理其他键
                    Map<String, Object> errorKeyInfo = new HashMap<>();
                    errorKeyInfo.put("key", key);
                    errorKeyInfo.put("type", "error");
                    errorKeyInfo.put("value", "获取失败: " + e.getMessage());
                    errorKeyInfo.put("size", 0);
                    errorKeyInfo.put("ttl", -2);
                    errorKeyInfo.put("exists", false);
                    keyInfoList.add(errorKeyInfo);
                }
            }

            result.put("success", true);
            result.put("pattern", pattern);
            result.put("keys", keyInfoList);
            result.put("count", keyInfoList.size());
            result.put("totalFound", keyNames.size());
        } catch (Exception e) {
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        return result;
    }
}